﻿/*
Copyright (c) 2010, hiSoft
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the hiSoft nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE HISOFT AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL HISOFT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;

namespace Orchard.Test.Library
{
    public class ContentTypeHelper:UIHelperBase
    {
        public ContentTypeHelper(TestLibrary settings) : base(settings){ }

        private int GetContentTypeIndexOnManageContentTypes(ContentType type)
        {
            var count = (int)selenium.GetXpathCount(ContentTypesLocator);
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("{0}[{1}]/div/div/h3", ContentTypesLocator, index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(type.DisplayName, text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find content type {0} on Manage ContentTypes page!", type.DisplayName));

            return index;
        }

        private int GetPartIndexOnListContentPartsPage(ContentPart part)
        {
            var count = (int)selenium.GetXpathCount(ContentPartsLocator);
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("{0}[{1}]/div/div/h3", ContentPartsLocator, index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(part.Name, text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find content part {0} on Content Parts page!", part.Name));

            return index;
        }

        private int GetPartIndexByNameOnAddPartsPage(ContentPart part)
        {
            int count = (int)selenium.GetXpathCount(PartsLocatorForAddParts);
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("{0}[{1}]/label", PartsLocatorForAddParts, index);
                var text = selenium.GetText(path);
                RemoveInvaildWhiteSpaceCharWhenCompare(part.Name,ref text);
                if (String.CompareOrdinal(part.Name, text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find part {0} in Add Parts page!", part.Name));

            return index;
        }

        private int GetPartIndexByNameOnEditContentTypePage(ContentPart part)
        {
            bool HaveFileds = ((int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset") == 2);
            int count = 0;
            if (!HaveFileds)
            {
                count = (int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset/fieldset");
            }
            else
            {
                count = (int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset[2]/fieldset");
            }
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = null;
                if (!HaveFileds)
                {
                    path = String.Format("//div[@class='manage-type']/fieldset/fieldset[{0}]/h3", index);
                }
                else
                {
                    path = String.Format("//div[@class='manage-type']/fieldset[2]/fieldset[{0}]/h3", index);
                }
                var text = selenium.GetText(path);
                RemoveInvaildWhiteSpaceCharWhenCompare(part.Name,ref text);             
                if (String.CompareOrdinal(part.Name, text) == 0)
                break; 
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find part {0} in Edit Content Type page!", part.Name));

            return index;
        }

        private int GetFieldIndexByNameOnEditContentTypePage(ContentField field)
        {
            //int count = (int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset/fieldset");
            int count = (int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset[1]/fieldset");  //Fields 
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("//div[@class='manage-type']/fieldset/fieldset[{0}]/h3", index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(String.Format("{0} (TextField)", field.Name), text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find field {0} in Edit Content Type page!", field.Name));

            return index;
        }

        private int GetFieldIndexByNameOnEditContentPartPage(ContentField field)
        {
            int count = (int)selenium.GetXpathCount("//div[@class='manage-part']/fieldset/fieldset");
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("//div[@class='manage-part']/fieldset/fieldset[{0}]/h3", index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(String.Format("{0} (TextField)", field.Name), text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find field {0} in Edit Content Type page!", field.Name));

            return index;
        }

        private void GoToEditContentType(ContentType type)
        {
            ManageContentTypes();
            ClickAndWait(String.Format("//a[@href='/Admin/ContentTypes/Edit/{0}']", type.TypeId));
        }

        private void GoToEditContentPart(ContentPart part)
        {
            ListContentParts();
            int index = GetPartIndexOnListContentPartsPage(part);
            ClickAndWait(String.Format("{0}[{1}]/div/div[2]/a", ContentPartsLocator, index));
        }

        public void ManageContentTypes()
        {
            selenium.Open("/Admin/ContentTypes");        
        }

        public void ListContentParts()
        {
            selenium.Open("/Admin/ContentTypes/listparts");
        }

        public bool IsContentPartExist(string contentPartName)
        {
            ListContentParts();
            if (selenium.IsTextPresent(contentPartName))
                return true;
            else return false;
        }

        public ContentType CreateContentType(string displayName)
        {
            return CreateContentType(displayName, null, false, false, null, null);
        }

        public ContentType CreateContentType(string displayName, List<ContentField> fields, List<ContentPart> parts)
        {
            return CreateContentType(displayName, null, false, false, fields, parts);           
        }

        public ContentType CreateContentType(string displayName, List<ContentField> fields, List<ContentPart> parts, bool clickSubmit)
        {

            return CreateContentType(displayName, null, false, false, fields, parts, false);
        }

        public ContentType CreateContentType(string displayName, string typeId, bool indexForSearch, bool showBugLink, List<ContentField> fields, List<ContentPart> parts)
        {
            return CreateContentType(displayName, typeId, indexForSearch, showBugLink, fields, parts, true);
        }

        public ContentType CreateContentType(string displayName, string typeId, bool indexForSearch, bool showBugLink, List<ContentField> fields, List<ContentPart> parts,bool clickSubmit)
        {
            if (String.IsNullOrEmpty(typeId))
            {
                typeId = displayName;
            }
            selenium.Open("/Admin/ContentTypes/Create");
            selenium.Type("DisplayName", displayName);
            selenium.Type("Name", typeId);
            Submit();//On create content type page

            if (parts != null && parts.Count != 0)
            {
                foreach (ContentPart part in parts)
                {
                    int partIndex = GetPartIndexByNameOnAddPartsPage(part);
                    selenium.Check(String.Format("{0}[{1}]/input", PartsLocatorForAddParts, partIndex));
                }
            }
            Submit();//On add parts page

            if (fields != null && fields.Count != 0)
            {
                foreach (ContentField field in fields)
                {
                    ClickAndWait("//div[@class='manage-type']/div[1]/a");
                    selenium.Type("DisplayName", field.Name);
                    Submit();  //On add fields page            
                }
            }

            if (indexForSearch)
            {
                string indexForSearchLocator = "//input[@id='TypeIndexing_Included']";
                if (selenium.IsElementPresent(indexForSearchLocator))
                {
                    selenium.Check(indexForSearchLocator);
                }
            }

            if (showBugLink)
            {
                string showBugLinkLocator = "//input[@id='DevToolsSettings_ShowDebugLinks']";
                if (selenium.IsElementPresent(showBugLinkLocator))
                {
                    selenium.Check(showBugLinkLocator);
                }
            }
            if(clickSubmit)
            Submit();

            return new ContentType(displayName, typeId, indexForSearch, showBugLink, fields, parts);
        }

        public ContentType CreateContentTypeWithoutFieldsAndParts(string displayName, string typeId)
        {
            if (String.IsNullOrEmpty(typeId))
            {
                typeId = displayName;
            }
            selenium.Open("/Admin/ContentTypes/Create");
            selenium.Type("DisplayName", displayName);
            selenium.Type("Name", typeId);
            Submit();          

            return new ContentType(displayName, typeId);
        }

        public ContentType RenameContentType(ContentType type, string newDisplayName)
        {
            return RenameContentType(type,newDisplayName,true);
        }

        public ContentType RenameContentType(ContentType type, string newDisplayName,bool submit)
        {
            GoToEditContentType(type);
            selenium.Type("DisplayName", newDisplayName);
            if(submit) Submit();
            type.DisplayName = newDisplayName;
            return type;
        }

        public ContentPart CreateContentPart(string name, List<ContentField> fields)
        {
            selenium.Open("/Admin/ContentTypes/CreatePart");
            selenium.Type("Name", name);
            Submit();
            if (fields != null && fields.Count != 0)
            {
                foreach (ContentField field in fields)
                {
                    ClickAndWait("//div[@class='manage add-to-type']/a");
                    selenium.Type("DisplayName", field.Name);
                    Submit();
                }
            }

            Submit();

            if (name == null)
            {
                return new ContentPart(null, fields);
            }
            return new ContentPart(name, fields);
        }

        public bool DeleteContentPart(string contentPartName)
        {
            return DeleteContentPart(new List<ContentPart> {new ContentPart(contentPartName)});
        }

        public bool DeleteContentPart(List<ContentPart> parts)
        {
            selenium.Open("/Admin/ContentTypes/ListParts");
           
            if (parts != null && parts.Count != 0)
            {
                foreach (ContentPart part in parts)
                {
                    string partId=(part.Name.Replace(" ","")+"Part").Trim();
                    ClickAndWait(string.Format("//a[contains(@href, '/Admin/ContentTypes/EditPart/{0}')]",partId));

                    selenium.Click("name=submit.Delete");
                    System.Threading.Thread.Sleep(3000);
                    if(!selenium.IsTextPresent(string.Format("\"{0}\" has been removed", part.Name)))
                        return false;
                    if(selenium.IsElementPresent(string.Format("//a[contains(@href, '/Admin/ContentTypes/EditPart/{0}')]",partId)))
                        return false;
                }
            }
            return true;           
        } 

        public ContentType AddContentPartToContentType(ContentType type, List<ContentPart> parts)
        { 
            if (type.Parts == null)
            {
                type.Parts = new List<ContentPart>();
            }

            GoToEditContentType(type);
            ClickAndWait("//div[@class='manage-type']/div[2]/a");
            if (parts != null && parts.Count != 0)
            {
                for (int i = 0; i < parts.Count; i++)
                {
                    int partIndex = GetPartIndexByNameOnAddPartsPage(parts[i]);
                    selenium.Click(String.Format("{0}[{1}]/input", PartsLocatorForAddParts, partIndex)); 
                    type.Parts.Add(parts[i]);
                }
            }
           
            Submit();         
            return type;
        }

        public ContentType AddContentFieldToContentType(ContentType type, ContentField field)
        {
            GoToEditContentType(type);
            ClickAndWait("//div[@class='manage-type']/div[1]/a");
            selenium.Type("DisplayName", field.Name);
            Submit();
            if (type.Fields == null)
            {
                type.Fields = new List<ContentField>();
            }
            if (!type.Fields.Contains(field))
            {
                type.Fields.Add(field);
            }
            return type;
        }

        public ContentType AddContentFieldToContentType(ContentType type, ContentField field,bool includeInIndex)
        {
            GoToEditContentType(type);
            ClickAndWait("//div[@class='manage-type']/div[1]/a");
            selenium.Type("DisplayName", field.Name);
            Submit();
            if (type.Fields == null)
            {
                type.Fields = new List<ContentField>();
            }
            if (!type.Fields.Contains(field))
            {
                type.Fields.Add(field);
            }
            if (includeInIndex)
            {
                GoToEditContentType(type);
                selenium.Click("//div[@id='content']/div/form/div/div/fieldset[1]/fieldset/h3/span[1]/span");
                selenium.Check("Fields_0__FieldIndexing_Included");
                Submit();
            }
            return type;
        }

        public ContentType EditContentType(ContentType type, string newContentTypeName,List<ContentField> fieldsToAdd, List<ContentField> fieldsToRemove, List<ContentPart> partsToAdd, List<ContentPart> partsToRemove)
        {
            //ContentType returnType = type;
            GoToEditContentType(type);
            if (!string.IsNullOrEmpty(newContentTypeName))
            {
               RenameContentType(type, newContentTypeName);
            }
            if (fieldsToAdd != null)
            {
                foreach (ContentField field in fieldsToAdd)
                    AddContentFieldToContentType(type, field);
            }
            if (fieldsToRemove != null)
            {
                foreach (ContentField field in fieldsToRemove)
                    RemoveContentFieldFromContentType(type, field);
            }
            if (partsToAdd != null)
            {
                 AddContentPartToContentType(type, partsToAdd);
            }
            if (partsToRemove != null)
            {
                foreach(ContentPart part in partsToRemove)
                    RemoveContentPartFromContentType(type, part);
            }
            return type;
        }

        //public bool DeleteContentType(ContentType type, string ContentTypeName)
        //{            
        //    GoToEditContentType(type);

        //    return true;
        //}

        public bool DeleteContentType(string typeDisplayName)
        {
            return DeleteContentType(new List<ContentType> { new ContentType(typeDisplayName,"")});
        }

        public bool DeleteContentType(List<ContentType> Types)
        {
           return DeleteContentType(Types, true);
        }

        public bool DeleteContentType(string typeDisplayName, bool confirmDelete)
        {
            return DeleteContentType(new List<ContentType> { new ContentType(typeDisplayName, "") }, confirmDelete);
        }

        public bool DeleteContentType(List<ContentType> Types,bool confirmDelete)
        {
            selenium.Open("/Admin/ContentTypes");
            if (Types != null && Types.Count != 0)
            {
                foreach (ContentType type in Types)
                {
                    string typeId = type.DisplayName.Replace(" ", "").Trim();
                    ClickAndWait(string.Format("//a[contains(@href, '/Admin/ContentTypes/Edit/{0}')]", typeId));
                    if (confirmDelete)
                    {
                        selenium.Click("name=submit.Delete");
                        System.Threading.Thread.Sleep(3000);
                        if (!selenium.IsTextPresent(string.Format("\"{0}\" has been removed", type.DisplayName)))
                            return false;
                        if (selenium.IsElementPresent(string.Format("//a[contains(@href, '/Admin/ContentTypes/Edit/{0}')]", typeId)))
                            return false;
                    }
                }
            }
            return true;  

        }

        public void EditContentPart(string  partName)
        {
            selenium.Open("/Admin/ContentTypes/ListParts");
            string partID = partName.Replace(" ", "").Trim();
            selenium.Click(string.Format("//a[contains(@href, '/Admin/ContentTypes/EditPart/{0}')]",partID+"Part"));
        }

        public ContentPart AddContentFieldToContentPart(ContentPart part, ContentField field)
        {
            GoToEditContentPart(part);
            ClickAndWait("//div[@class='manage add-to-type']/a");     
            selenium.Type("DisplayName", field.Name);
            Submit();

            if (part.Fields == null)
            {
                part.Fields = new List<ContentField>();
            }

            if (!part.Fields.Contains(field))
            {
                part.Fields.Add(field);
            }
            return part;
        }

        public ContentType RemoveContentPartFromContentType(ContentType type, ContentPart part)
        {
            GoToEditContentType(type);
            int fieldsetCount = (int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset");
            bool HaveFileds = (fieldsetCount == 2);

            int partIndex = GetPartIndexByNameOnEditContentTypePage(part);

            if (!HaveFileds)
            {
                ClickAndWait(String.Format("//div[@class='manage-type']/fieldset/fieldset[{0}]/div/a", partIndex));
            }
            else
            {
                ClickAndWait(String.Format("//div[@class='manage-type']/fieldset[2]/fieldset[{0}]/div/a", partIndex));
            }

            Submit();
            if (type.Parts != null && type.Parts.Contains(part))
            {
                type.Parts.Remove(part);
            }

            return type;
        }

        public ContentType RemoveContentFieldFromContentType(ContentType type, ContentField field)
        {
            GoToEditContentType(type);
            int fieldIndex = GetFieldIndexByNameOnEditContentTypePage(field);
            ClickAndWait(String.Format("//div[@class='manage-type']/fieldset/fieldset[{0}]/div/a", fieldIndex));
            Submit();
            if (type.Fields != null && type.Fields.Contains(field))
            {
                type.Fields.Remove(field);
            }
            return type;
        }

        public ContentPart RemoveContentFieldFromContentPart(ContentPart part, ContentField field)
        {
            GoToEditContentPart(part);
            if (part.Fields != null && part.Fields.Contains(field))
            {
                int fieldIndex = GetFieldIndexByNameOnEditContentPartPage(field);
                selenium.Click(String.Format("//div[@class='manage-part']/fieldset/fieldset[{0}]/div/a", fieldIndex));
                part.Fields.Remove(field);
            }
            return part;
        }   

        public int GetPartCountOnAddPartsPage()
        {
            ListContentParts();
            return (int)selenium.GetXpathCount(PartsLocatorForAddParts);
        }

        public void CreateContentOfType(ContentType type)
        {
            selenium.Open(String.Format("/Admin/Contents/Create/{0}", type.DisplayName));     
            for (int i = 0; i < type.Fields.Count; i++)
            {
                selenium.Type(String.Format("//input[@id='{0}_{1}_Value']",type.DisplayName,type.Fields[i].Name),UIHelperBase.GenerateUniqueIdentifier());
            }
            Submit();
        }

        public string CreateContentOfTypeWithReturnID(ContentType type)
        {
            selenium.Open(String.Format("/Admin/Contents/Create/{0}", type.DisplayName));
            for (int i = 0; i < type.Fields.Count; i++)
            {
                selenium.Type(String.Format("//input[@id='{0}_{1}_Value']", type.DisplayName, type.Fields[i].Name), UIHelperBase.GenerateUniqueIdentifier());
            }
            Submit();
            string strUrl = selenium.GetLocation();
            return (strUrl.Substring(strUrl.LastIndexOf('/')+1));
        }

         public string CreateContentOfType(ContentType type, string contentTitle, string contentContainer, string contentSlug, bool setAsHomePage, string contentOwner, bool publishNow)
        {
            selenium.Open(String.Format("/Admin/Contents/Create/{0}", type.DisplayName));

            if(contentContainer.Trim().Length>0) selenium.Select("Containable_ContainerId", String.Format("label=List: {0}", contentContainer));
            selenium.Type("Routable_Title", contentTitle);
            selenium.Type("Routable_Slug", contentSlug);
            if (setAsHomePage != selenium.IsChecked("Routable_PromoteToHomePage"))
            {
                selenium.Click("Routable_PromoteToHomePage");
            }
            if (contentOwner.Trim().Length > 0) selenium.Type("OwnerEditor_Owner", contentOwner);
            if (publishNow)
            {
                selenium.Click("//button[@name='submit.Publish']");
            }
            else
            {
                selenium.Click("//button[@name='submit.Save']");
            }
            selenium.WaitForPageToLoad(TestLibrary.Consts.TimeToWaitForPageToLoad);
            string strUrl = selenium.GetLocation();
            return (strUrl.Substring(strUrl.LastIndexOf('/')+1));
        }

        public void ListItemsOfContentType(ContentType type)
        {
            ManageContentTypes();
            int index = GetContentTypeIndexOnManageContentTypes(type);
            ClickAndWait(String.Format("{0}[{1}]/div/div[2]/a[1]", ContentTypesLocator, index));
        }

        public bool IsContentTypeExist_byEditLink(ContentType contentType)
        {
            if (selenium.IsElementPresent(string.Format("//a[contains(@href, '/Admin/ContentTypes/Edit/{0}')]", contentType.TypeId)))
                return true;
            else return false;  
        }
       
        public void ClickArrowOfContentPart(ContentPart contentPart)
        {
            bool HaveFileds = ((int)selenium.GetXpathCount("//div[@class='manage-type']/fieldset") == 2);
            int index = GetPartIndexByNameOnEditContentTypePage(contentPart);
            if (HaveFileds)
                selenium.Click(string.Format(string.Format("//div[@id='content']/div/form/div/div/fieldset[2]/fieldset[{0}]/h3/span/span",index)));
            else selenium.Click(string.Format(string.Format("//div[@id='content']/div/form/div/div/fieldset/fieldset[{0}]/h3/span/span",index)));
        }

        public void ConfigContentPart_CommonSettings(bool ShowEditorForCreationDateTime, bool ShowEditorforOwner)
        {            
            ClickArrowOfContentPart(new ContentPart("Common"));
            int index = GetPartIndexByNameOnEditContentTypePage(new ContentPart("Common")) - 1;
            if (index < 0) return;
            if (ShowEditorForCreationDateTime)
                selenium.Check(string.Format("Parts_{0}__DateEditorSettings_ShowDateEditor",index));
            else selenium.Uncheck(string.Format("Parts_{0}__DateEditorSettings_ShowDateEditor",index));
            if (ShowEditorforOwner)
                selenium.Check(string.Format("Parts_{0}__OwnerEditorSettings_ShowOwnerEditor",index));
            else selenium.Uncheck(string.Format("Parts_{0}__OwnerEditorSettings_ShowOwnerEditor", index));
            Submit();
        }

        /// <summary>
        /// Because In FF5.0 & FF6.0, selenium get text is different from display in UI, maybe with a odd char which don't desired.
        /// This function just remove this odd char, normally it appear at the first position of String that get by selenium from webpage in FF.
        /// </summary>
        /// <param name="myText">target text</param>
        /// <param name="textGetBySelenium">String that get by selenium from webpage in FF</param>
        public void RemoveInvaildWhiteSpaceCharWhenCompare(string myText,ref string textGetBySelenium)
        {
              for (int i = 0; i < textGetBySelenium.Length; i++)
                {
                    if (String.CompareOrdinal(myText, textGetBySelenium) == 0)
                        break;
                    else
                    {
                        for (int j = 0; j < TestLibrary.Consts.whitespaceChars.Length; j++)
                        {
                            if (string.CompareOrdinal(TestLibrary.Consts.whitespaceChars[j], textGetBySelenium[i].ToString()) == 0)
                            {
                                textGetBySelenium = textGetBySelenium.Remove(i, 1);
                                break;
                            }
                        }
                    }
                }
            
        }

    }

    public class ContentType
    {
        public string DisplayName { get; set; }

        public string TypeId { get; set; }

        public bool IndexForSearch { get; set; }

        public bool ShowBugLink { get; set; }

        public List<ContentField> Fields { get; set; }

        public List<ContentPart> Parts { get; set; }

        public ContentType(string displayName, string typeId)
        {
            DisplayName = displayName;
            TypeId = typeId;
        }

        public ContentType(string displayName, List<ContentField> fields, List<ContentPart> parts)
        {
            DisplayName = displayName;            
            if (fields != null && fields.Count != 0)
            {
                Fields = new List<ContentField>();
                foreach (ContentField field in fields)
                {
                    Fields.Add(field);
                }
            }

            if (parts != null && parts.Count != 0)
            {
                Parts = new List<ContentPart>();
                foreach (ContentPart part in parts)
                {
                    Parts.Add(part);
                }
            }
        }

        public ContentType(string displayName, string typeId, bool indexForSearch, bool showBugLink, List<ContentField> fields, List<ContentPart> parts)
        {
            DisplayName = displayName;
            TypeId = typeId;
            IndexForSearch = indexForSearch;
            ShowBugLink = showBugLink;
            if (fields != null && fields.Count != 0)
            {
                Fields = new List<ContentField>();
                foreach (ContentField field in fields)
                {
                    Fields.Add(field);
                }
            }

            if (parts != null && parts.Count != 0)
            {
                Parts = new List<ContentPart>();
                foreach (ContentPart part in parts)
                {
                    Parts.Add(part);
                }
            }
        }
    }

    public class ContentField
    {
        public string Name { get; set; }
        public FieldType FieldType { get; set; }
        public ContentField(string name, FieldType filedType)
        {
            Name = name;
            FieldType = filedType;
        }
    }

    public class ContentPart
    {
        public string Name { get; set; }

        public List<ContentField> Fields { get; set; }

        public ContentPart(string name)
        {
            Name = name;
        }

        public ContentPart(string name, List<ContentField> fields)
        {
            Name = name;
            if (fields != null && fields.Count != 0)
            {
                Fields = new List<ContentField>();
                foreach (ContentField field in fields)
                {
                    Fields.Add(field);
                }
            }
        }
    }

    public enum FieldType
    {
        TextField
    }
   
}
